/*
 * Copyright 2011-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0.
 * See `LICENSE` in the project root for license information.
 */

package me.ijleex.mgmt.framework.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.LongAdder;

/**
 * 信号量 使用示例
 *
 * @author liym
 * @since 2020-05-28 14:13 新建
 */
public final class SemaphoreDemo {

    private static final Semaphore FULL = new Semaphore(5);
    private static final Semaphore MUTEX = new Semaphore(1);
    private static final Semaphore EMPTY = new Semaphore(0);

    // private static volatile int count = 0;
    private static final LongAdder COUNT = new LongAdder();

    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        threadPool.execute(() -> {
            // noinspection InfiniteLoopStatement
            while (true) {
                try {
                    FULL.acquire();
                    MUTEX.acquire();

                    COUNT.increment();

                    System.out.println("生产了 1 个资源，目前还有 " + COUNT.longValue() + " 个资源");
                    Thread.sleep(1_000L);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                } finally {
                    MUTEX.release();
                    EMPTY.release();
                }
            }
        });

        threadPool.execute(() -> {
            // noinspection InfiniteLoopStatement
            while (true) {
                try {
                    EMPTY.acquire();
                    MUTEX.acquire();

                    COUNT.decrement();

                    System.err.println("消费了 1 个资源，目前还有 " + COUNT.longValue() + " 个资源");
                    Thread.sleep(1_000L);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(e);
                } finally {
                    MUTEX.release();
                    FULL.release();
                }
            }
        });
    }

}
